package ar.edu.utn.frsf.cidisi.upcolbpip2pn.generator.petrinet;

import org.eclipse.emf.common.util.EList;
import java.util.HashMap;
import java.util.Set;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.*;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Exception;;

public class Upcolbpip2PN
{
  protected static String nl;
  public static synchronized Upcolbpip2PN create(String lineSeparator)
  {
    nl = lineSeparator;
    Upcolbpip2PN result = new Upcolbpip2PN();
    nl = null;
    return result;
  }

  public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
  protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>" + NL + "<!DOCTYPE workspaceElements PUBLIC \"-//CPN//DTD CPNXML 1.0//EN\" \"http://www.daimi.au.dk/~cpntools/bin/DTD/6/cpn.dtd\">" + NL + "" + NL + "<workspaceElements>" + NL + "  <generator tool=\"CPN Tools\"" + NL + "             version=\"2.2.0\"" + NL + "             format=\"6\"/>" + NL + "  <cpnet>" + NL + "\t";
  protected final String TEXT_2 = NL + "\t";
  protected final String TEXT_3 = NL + "    <page id=\"ID400000\">" + NL + "      <pageattr name=\"";
  protected final String TEXT_4 = "\"/>" + NL + "\t";
  protected final String TEXT_5 = NL + "\t";
  protected final String TEXT_6 = NL + "\t";
  protected final String TEXT_7 = NL + "\t";
  protected final String TEXT_8 = NL + NL + NL + "\t";
  protected final String TEXT_9 = NL + "\t";
  protected final String TEXT_10 = NL + "\t";
  protected final String TEXT_11 = NL + "\t\t\t\t";
  protected final String TEXT_12 = NL + "\t\t\t\t";
  protected final String TEXT_13 = NL + "\t\t\t";
  protected final String TEXT_14 = NL + "\t\t\t";
  protected final String TEXT_15 = NL + "\t\t\t";
  protected final String TEXT_16 = NL + "\t\t\t";
  protected final String TEXT_17 = NL + "\t\t";
  protected final String TEXT_18 = NL + "\t\t";
  protected final String TEXT_19 = NL + "\t\t";
  protected final String TEXT_20 = NL + "\t\t";
  protected final String TEXT_21 = NL + "\t\t";
  protected final String TEXT_22 = NL + "\t\t";
  protected final String TEXT_23 = NL;
  protected final String TEXT_24 = NL + "\t\t\t";
  protected final String TEXT_25 = NL + "\t\t\t";
  protected final String TEXT_26 = NL + "\t\t";
  protected final String TEXT_27 = NL + "\t\t";
  protected final String TEXT_28 = NL + "\t\t";
  protected final String TEXT_29 = NL + "\t\t";
  protected final String TEXT_30 = NL + "\t\t";
  protected final String TEXT_31 = NL + "\t\t";
  protected final String TEXT_32 = NL + "\t\t";
  protected final String TEXT_33 = NL + "\t\t";
  protected final String TEXT_34 = NL + "\t\t";
  protected final String TEXT_35 = NL + "\t\t";
  protected final String TEXT_36 = NL + "\t";
  protected final String TEXT_37 = NL + "\t";
  protected final String TEXT_38 = NL + "\t";
  protected final String TEXT_39 = NL + NL + "    </page>" + NL;
  protected final String TEXT_40 = NL + "\t\t";
  protected final String TEXT_41 = NL + "\t\t";
  protected final String TEXT_42 = NL + NL + "    <fusion id=\"ID6989900\"" + NL + "            name=\"termination\">";
  protected final String TEXT_43 = NL + "\t\t<fusion_elm idref=\"";
  protected final String TEXT_44 = "\"/>" + NL + "\t\t";
  protected final String TEXT_45 = NL + "    </fusion>" + NL + "   " + NL + "    <instances>" + NL + "      <instance id=\"ID600000\"" + NL + "                page=\"ID400000\">";
  protected final String TEXT_46 = NL;
  protected final String TEXT_47 = NL + "      </instance>" + NL + "    </instances>" + NL + "    " + NL + "    " + NL + "  </cpnet>" + NL + "</workspaceElements>";

  public String generate(Object argument)
  {
    final StringBuffer stringBuffer = new StringBuffer();
     InteractionProtocol interactionProtocol = (InteractionProtocol) argument; 
    stringBuffer.append(TEXT_1);
    
	GlobboxDefinition globboxDef = GlobboxDefinition.create(null);
	
    stringBuffer.append(TEXT_2);
    stringBuffer.append( globboxDef.generate(null));
    stringBuffer.append(TEXT_3);
    stringBuffer.append( "IP"+interactionProtocol.getName());
    stringBuffer.append(TEXT_4);
    

	// Inicializa los id de objetos y atributos de la transformacion.- 
	GlobalValues.reset();	
	
	Place2PN place2pn = Place2PN.create(null);

	Place place = new Place("protocol_start");
	place.setInitialMarking(true);
	
    stringBuffer.append(TEXT_5);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_6);
    
	
	Transition2PN transition2pn = Transition2PN.create(null);

	Transition transition = new Transition("protocol_start_ev");
	
    stringBuffer.append(TEXT_7);
    stringBuffer.append( transition2pn.generate(transition));
    stringBuffer.append(TEXT_8);
    
	Arc2PN arc2PN = Arc2PN.create(null);

	Arc arc = new Arc(place, transition, Arc.PLACE_TO_TRANSITION);
	
    stringBuffer.append(TEXT_9);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_10);
    	

	String INPUT_PORT_MSG = "ID1227512";
	String OUTPUT_PORT_MSG = "ID1229891";
	
//	EList<InteractionProtocolElement> ipElements = interactionProtocol.getIpElement();
	EList<InteractionProtocolElement> ipElements = interactionProtocol.getOrderedIpElement();
	
	
	Transition lastTransition = transition;
//    for (InteractionProtocolElement ipElement : ipElements) {
    for (int i=0;i<ipElements.size();i++) {
    	InteractionProtocolElement ipElement = ipElements.get(i);

		if (i>0){
			SubPage sp = GlobalValues.subpagesMap.get(ipElements.get(i-1));
			if (sp!=null){
				place = sp.getTransitionOutput();
				if (place==null){
					place = new Place(ipElement.getName());
				}
				
    stringBuffer.append(TEXT_11);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_12);
    
			} else{
			place = new Place(ipElement.getName());
			
    stringBuffer.append(TEXT_13);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_14);
    
		}
		} else{
			place = new Place(ipElement.getName());
			
    stringBuffer.append(TEXT_15);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_16);
    
		}
		
		arc = new Arc(place, lastTransition, Arc.TRANSITION_TO_PLACE);
		
    stringBuffer.append(TEXT_17);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_18);
    
		
		// El generate de esta transition esta mas abajo
		transition = new Transition("t_"+ipElement.getName());

		lastTransition = transition;
		
		arc = new Arc(place, transition, Arc.PLACE_TO_TRANSITION);
		
    stringBuffer.append(TEXT_19);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_20);
    

		SubPage subPage = null;
		
		if (ipElement instanceof BusinessMessage){

	/*		
			if (!GlobalValues.msg){	// Se ejecuta la primera vez que aparece un mensaje.-
				subPage = new SubPage(ipElement.getName(), place, INPUT_PORT_MSG, OUTPUT_PORT_MSG);
				subPage.setId("ID1217348");
				transition.setSubPage(subPage);
				GlobalValues.msgSubPage = subPage;
				
				
				Instance newInstance = new Instance(transition);
				newInstance.setSubPageId(transition.getId());
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);
				
				
				// Al setear msg = true el patron del mensaje se va a ejecutar solo una vez.-
				GlobalValues.msg = true;
				BusinessMessage2PN businessMessage2PN = BusinessMessage2PN.create(null);
				String bm2pn = businessMessage2PN.generate((BusinessMessage)ipElement);
				GlobalValues.pages.put(ipElement, bm2pn);
				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
				
			}else{
//				subPage = new SubPage(ipElement.getName(), place, GlobalValues.msgSubPage.getSubnetInput(), GlobalValues.msgSubPage.getSubnetOutput());
				subPage = new SubPage(ipElement.getName(), place, INPUT_PORT_MSG, OUTPUT_PORT_MSG);
				subPage.setId("ID1217348");
				transition.setSubPage(subPage);
				
				Instance newInstance = new Instance(transition);
				newInstance.setSubPageId(transition.getId());
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
				
				
			}
			GlobalValues.subpagesMap.put(ipElement,subPage);
			*/

			
			

		} else if (ipElement instanceof ControlFlowSegment){
			subPage = new SubPage(ipElement.getName(), place);
			transition.setSubPage(subPage);
			GlobalValues.subpagesMap.put(ipElement,subPage);
			
			ControlFlowSegment cfs = (ControlFlowSegment)ipElement;
			if (cfs instanceof Cancel){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				Cancel2PN cancel2pn = Cancel2PN.create(null);
				String cancel2pnStr = cancel2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, cancel2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else 	if (cfs instanceof Exception){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				Exception2PN exception2pn = Exception2PN.create(null);
				String exception2pnStr = exception2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, exception2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof Xor){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				Xor2PN xor2pn = Xor2PN.create(null);
				String xor2pnStr = xor2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, xor2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof And){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				And2PN and2pn = And2PN.create(null);
				String and2pnStr = and2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, and2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof Or){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				OrSyncMerge2PN orSyncMerge2pn = OrSyncMerge2PN.create(null);
				String orSyncMerge2pnStr = orSyncMerge2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, orSyncMerge2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof If){

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				If2PN if2pn = If2PN.create(null);
				String if2pnStr = if2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, if2pnStr);				
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof Loop){ 

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				if (((Loop)cfs).getLoopType().equals(LoopType.WHILE)){ //While
					While2PN while2pn = While2PN.create(null);
					String while2pnStr = while2pn.generate(cfs);
					GlobalValues.pages.put(ipElement, while2pnStr);		
				} else { //Until
					For2PN for2pn = For2PN.create(null);
					String for2pnStr = for2pn.generate(cfs);
					GlobalValues.pages.put(ipElement, for2pnStr);		
					
				}
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			} else if (cfs instanceof MultipleInstance){ 

				
				Instance newInstance = new Instance(transition);
				Instances instances = Instances.create(null);
				GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

				MI2PN mi2pn = MI2PN.create(null);
				String mi2pnStr = mi2pn.generate(cfs);
				GlobalValues.pages.put(ipElement, mi2pnStr);		
				
				GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
				GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
			}
			
		} else if (ipElement instanceof Termination && ipElement.getSuccessor()!=null){
			subPage = new SubPage(((Termination)ipElement).getTerminationElement().getName()+GlobalValues.pageId, place);
			transition.setSubPage(subPage);
			GlobalValues.subpagesMap.put(ipElement,subPage);
			
			Termination termination = (Termination)ipElement;
				
			Instance newInstance = new Instance(transition);
			Instances instances = Instances.create(null);
			GlobalValues.instancesStr = GlobalValues.instancesStr + instances.generate(newInstance);

			Termination2PN termination2pn = Termination2PN.create(null);
			String termination2pnStr = termination2pn.generate(termination);
			GlobalValues.pages.put(ipElement, termination2pnStr);				
			
			GlobalValues.instancesStr = GlobalValues.instancesStr + "</instance>";
			GlobalValues.instancesMap.put(ipElement, GlobalValues.instancesStr);
		}
		
		
    stringBuffer.append(TEXT_21);
    stringBuffer.append( transition2pn.generate(transition));
    stringBuffer.append(TEXT_22);
    
	}

    stringBuffer.append(TEXT_23);
    
	if (ipElements.size()>0){
		SubPage sp = GlobalValues.subpagesMap.get(ipElements.get(ipElements.size()-1));
		if (sp!=null){
			place = sp.getTransitionOutput();
			if (place==null){
				place = new Place("implicit_termination_start");
			}
			
    stringBuffer.append(TEXT_24);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_25);
    
		} else{
		place = new Place("implicit_termination_start");
		
    stringBuffer.append(TEXT_26);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_27);
    
		}

		arc = new Arc(place, lastTransition, Arc.TRANSITION_TO_PLACE);
		
    stringBuffer.append(TEXT_28);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_29);
    
		
		transition = new Transition("implicit_termination_ev");
		
    stringBuffer.append(TEXT_30);
    stringBuffer.append( transition2pn.generate(transition));
    stringBuffer.append(TEXT_31);
    
	
		arc = new Arc(place, transition, Arc.PLACE_TO_TRANSITION);
		
    stringBuffer.append(TEXT_32);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_33);
    		
	} else {
	
		transition = new Transition("implicit_termination_ev");
		
    stringBuffer.append(TEXT_34);
    stringBuffer.append( transition2pn.generate(transition));
    stringBuffer.append(TEXT_35);
    
	}

	
	place = new Place("Success",true);
	// Agrego el place de terminacion a la lista de places fusionados.-
	GlobalValues.fusionPlaces.add(place);
	
    stringBuffer.append(TEXT_36);
    stringBuffer.append( place2pn.generate(place));
    stringBuffer.append(TEXT_37);
    
	
	arc = new Arc(place, transition, Arc.TRANSITION_TO_PLACE);
	
    stringBuffer.append(TEXT_38);
    stringBuffer.append( arc2PN.generate(arc));
    stringBuffer.append(TEXT_39);
    
	
	Set<Object> pagesSet = GlobalValues.pages.keySet();
	
	for (Object page : pagesSet){
		String pageStr = GlobalValues.pages.get(page);
		
    stringBuffer.append(TEXT_40);
    stringBuffer.append( pageStr);
    stringBuffer.append(TEXT_41);
    
	}
	

    stringBuffer.append(TEXT_42);
    
	for (Place p : GlobalValues.fusionPlaces){
		
    stringBuffer.append(TEXT_43);
    stringBuffer.append( p.getId());
    stringBuffer.append(TEXT_44);
    
	}

    stringBuffer.append(TEXT_45);
    stringBuffer.append(TEXT_46);
    stringBuffer.append( GlobalValues.instancesStr);
    stringBuffer.append(TEXT_47);
    return stringBuffer.toString();
  }
}
